package cn.amossun.starter.event.handler;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.amossun.starter.event.annoation.*;
import cn.amossun.starter.event.property.EventContext;
import cn.amossun.starter.event.property.EventExchangeContext;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Data
@Slf4j
public class EventExchangeContextProcessor implements ExchangeContextHolder {

    private EventContext eventContext;

    public EventExchangeContextProcessor(EventContext eventContext) {
        this.eventContext = eventContext;
    }

    @Override
    public void processListener(Object bean, String beanName, Method method) {
        EventListener eventListener = AnnotationUtils.findAnnotation(method, EventListener.class);
        if (eventListener != null) {
            eventContext.addExchanges(buildEventExchangeContexts(eventListener));
        }
    }

    @Override
    public void processPublisher(Object bean, String beanName, Method method) {
        EventPublisher eventPublisher = AnnotationUtils.findAnnotation(method, EventPublisher.class);
        if (eventPublisher != null) {
            eventContext.addExchange(buildEventExchangeContexts(eventPublisher));
        }
    }

    @Override
    public void processMulticaster(Object bean, String beanName, Method method) {
        EventMulticaster eventMulticaster = AnnotationUtils.findAnnotation(method, EventMulticaster.class);
        if (eventMulticaster != null) {

        }
    }

    @Override
    public List<EventExchangeContext> buildEventExchangeContexts(EventListener eventListener) {
        if(eventListener.bindings().length > 0
                && CollectionUtil.isNotEmpty(Arrays.stream(eventListener.bindings()).map(EventBinding::exchange).collect(Collectors.toList()))){

            return Arrays.stream(eventListener.bindings()).map(EventBinding::exchange).map(eventExchange -> {
                return process(eventExchange);
            }).collect(Collectors.toList());
        }

        /*String defaultExchangeName = getDefaultExchangeName(eventListener.defaultTopicExchange(), eventListener.defaultHeadersExchange());

        ExchangeTypeEnum exchangeTypeEnum = getDefaultExchangeTypeEnum(eventListener.defaultTopicExchange(), eventListener.defaultHeadersExchange());

        Map<String, Object> argumentsMap = getArguments(eventListener.arguments());
        EventExchangeContext eventExchangeContext = new EventExchangeContext(
                defaultExchangeName,
                exchangeTypeEnum,
                DurabilityEnum.DURABLE,
                eventListener.autoDelete(),
                Boolean.FALSE,
                argumentsMap);
        return Arrays.asList(eventExchangeContext);*/
        return null;
    }

    @Override
    public EventExchangeContext buildEventExchangeContexts(EventPublisher eventPublisher) {
        if(eventPublisher.binding() != null && eventPublisher.binding().exchange() != null &&
                StrUtil.isNotEmpty(eventPublisher.binding().exchange().name()) && StrUtil.isNotEmpty(eventPublisher.binding().exchange().value())) {
            return process(eventPublisher.binding().exchange());
        }

        if(eventPublisher.exchange() != null && StrUtil.isNotEmpty(eventPublisher.exchange().name()) && StrUtil.isNotEmpty(eventPublisher.exchange().value())){
            return process(eventPublisher.exchange());
        }

        /*String defaultExchangeName = getDefaultExchangeName(eventPublisher.defaultTopicExchange(), eventPublisher.defaultHeadersExchange());

        ExchangeTypeEnum exchangeTypeEnum = getDefaultExchangeTypeEnum(eventPublisher.defaultTopicExchange(), eventPublisher.defaultHeadersExchange());

        Map<String, Object> argumentsMap = getArguments(eventPublisher.arguments());
        EventExchangeContext eventExchangeContext = new EventExchangeContext(
                defaultExchangeName,
                exchangeTypeEnum,
                DurabilityEnum.DURABLE,
                Boolean.FALSE,
                Boolean.FALSE,
                argumentsMap);
        return eventExchangeContext;*/
        return null;
    }

}
